package com.ruicar.afs.cloud.manage.common.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.basic.api.fegin.info.BasicInfoFeign;
import com.ruicar.afs.cloud.basic.api.fegin.loanchange.LoanChangeFegin;
import com.ruicar.afs.cloud.bizcommon.cms.dto.CmsCheckRequestDTO;
import com.ruicar.afs.cloud.bizcommon.cms.dto.CmsContractCloseRequestDTO;
import com.ruicar.afs.cloud.bizcommon.cms.dto.CmsResponse;
import com.ruicar.afs.cloud.bizcommon.cms.dtoresponse.CmsContractInfo;
import com.ruicar.afs.cloud.bizcommon.cms.dtoresponse.CmsQueryContractResponseDTO;
import com.ruicar.afs.cloud.bizcommon.cms.enums.CodeResponseEnum;
import com.ruicar.afs.cloud.bizcommon.cms.enums.SuccessResponseEnum;
import com.ruicar.afs.cloud.bizcommon.cms.feign.CmsPlanChangeFeign;
import com.ruicar.afs.cloud.common.config.ContractFeginConfig;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.api.dto.BasicExpenseRecordDetailDto;
import com.ruicar.afs.cloud.manage.api.feign.info.BasicMainInfoFeign;
import com.ruicar.afs.cloud.manage.common.condition.ApplyRecordCondition;
import com.ruicar.afs.cloud.manage.common.entity.ManageApplyRecord;
import com.ruicar.afs.cloud.manage.common.entity.ManageCostExemptBill;
import com.ruicar.afs.cloud.manage.common.entity.ManagePrepaymentApply;
import com.ruicar.afs.cloud.manage.common.entity.ManageRevokeHandle;
import com.ruicar.afs.cloud.manage.common.service.ManageApplyRecordService;
import com.ruicar.afs.cloud.manage.common.service.ManageCostExemptBillService;
import com.ruicar.afs.cloud.manage.common.service.ManagePrepaymentApplyService;
import com.ruicar.afs.cloud.manage.common.service.ManageRevokeHandleService;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: xudongdong
 * @date: 2020/7/3
 * @description: 合同系统弹框双击校验，（根据合同号校验是否可以办理业务）
 */
@Slf4j
@RestController
@RequestMapping("/applyRecord")
@AllArgsConstructor
public class ApplyRecordController {

    private final LoanChangeFegin loanChangeFegin;
    private final BasicMainInfoFeign basicMainInfoFeign;
    private final ContractFeginConfig contractFeginConfig;
    private final ManageApplyRecordService manageApplyRecordService;
    private final ManagePrepaymentApplyService managePrepaymentApplyService;
    private final BasicInfoFeign basicInfoFeign;
    private final ManageRevokeHandleService manageRevokeHandleService;
    private final ManageCostExemptBillService manageCostExemptBillService;
    private final CmsPlanChangeFeign cmsCheckFeign;

    @ApiOperation(value = "根据合同号校验是否可以办理业务")
    @PostMapping("/findByContractNo")
    public IResponse findByContractNo(@RequestBody ApplyRecordCondition applyRecordCondition) {
        List<ManageApplyRecord> list = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getContractNo, applyRecordCondition.getContractNo())
                .in(EmptyUtils.isNotEmpty(applyRecordCondition.getContractBusiness()), ManageApplyRecord::getContractBusiness, applyRecordCondition.getContractBusiness())
                .in(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW, CaseStatusEnum.NO_SUBMISSION, CaseStatusEnum.SUBMISSION));
        if (list.size() > 0) {
            return IResponse.fail((list.get(0).getContractBusiness().getDesc()) + "的业务未闭环，无法继续!");
        }
        //除保险业务，其他业务均需要校验合同是否关闭、是否取消
        if (ContractBusinessEnum.insurance != applyRecordCondition.getHandleBusiness()) {
            return checkCloseOrCancel(applyRecordCondition.getContractNo(),applyRecordCondition.getDataSource());
        }
        //还款日变更校验
        if (ContractBusinessEnum.repaymentDateChange == applyRecordCondition.getHandleBusiness()) {
            return repaymentPlanValid(applyRecordCondition.getContractNo());
        }
        //豁免单校验
        if (ContractBusinessEnum.costExemptBill == applyRecordCondition.getHandleBusiness()) {
            return exemptCostValid(applyRecordCondition.getContractNo());
        }
        //费用豁免有无检验
        if (ContractBusinessEnum.costExempt == applyRecordCondition.getHandleBusiness()) {
            return hasCostExemptCheck(applyRecordCondition.getContractNo());
        }

        //合同取消校验
        if (ContractBusinessEnum.cancelContract == applyRecordCondition.getHandleBusiness()) {
            return cancelContractValid(applyRecordCondition.getContractNo(), applyRecordCondition.getIsSP());
        }
        //豁免罚息校验
        if (ContractBusinessEnum.exemptTypes == applyRecordCondition.getHandleBusiness()) {
            return penaltyExemptValid(applyRecordCondition.getContractNo());
        }
        //收款撤销校验
        if (ContractBusinessEnum.collectionRevoke == applyRecordCondition.getHandleBusiness()) {
            return collectionRevokeValid(applyRecordCondition.getContractNo());
        }
        //收款撤销成功处理
        if (ContractBusinessEnum.revokeHandle == applyRecordCondition.getHandleBusiness()) {
            return revokeHandleValid(applyRecordCondition.getContractNo());
        }
        //提前还款发起校验
        if (ContractBusinessEnum.advanceSettle == applyRecordCondition.getHandleBusiness()) {
            return this.getEarlyRepay(applyRecordCondition.getContractNo());
        }
        /**  月供对公收款发起校验 by ZC.GUO  **/
        if (ContractBusinessEnum.corporateSettlementRent == applyRecordCondition.getHandleBusiness()) {
            boolean back = this.canStartCorporateForRent(applyRecordCondition.getContractNo());
            if (back) {
                return IResponse.fail("该合同正在流程审核中，无法再次发起！");
            }
        }
        /**  提前还款对公收款发起校验 by ZC.GUO  **/
        if (ContractBusinessEnum.corporateSettlementPrepayment == applyRecordCondition.getHandleBusiness()) {
            boolean back = this.canStartCorporateForPrepayment(applyRecordCondition.getContractNo());
            if (back) {
                return IResponse.fail("该合同正在流程审核中，无法再次发起！");
            }
        }

        return IResponse.success(true);
    }

    /**
     * 豁免单校验
     */
    private IResponse exemptCostValid(String contractNo) {
        ManageCostExemptBill one = manageCostExemptBillService.getOne(Wrappers.<ManageCostExemptBill>query().lambda()
                .eq(ManageCostExemptBill::getContractNo, contractNo)
                .eq(ManageCostExemptBill::getProcessStatus, ProcessStatusEnum.draft)
        );
        if (EmptyUtils.isNotEmpty(one)) {
            return IResponse.fail("同一个合同号不能存在两个豁免单草稿状态！");
        }
        return IResponse.success(true);
    }

    /**
     * 还款日变更校验
     */
    private IResponse repaymentPlanValid(String contractNo) {
        List<ManageApplyRecord> advanceSettle = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>query().lambda()
                .eq(ManageApplyRecord::getContractNo, contractNo)
                .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.advanceSettle)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW));
        if (EmptyUtils.isNotEmpty(advanceSettle) && advanceSettle.size() > 0) {
            return IResponse.fail("提前结清业务审核中，无法申请！");
        }
        List<ManageApplyRecord> collectionRevoke = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>query().lambda()
                .eq(ManageApplyRecord::getContractNo, contractNo)
                .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.collectionRevoke)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW));
        if (EmptyUtils.isNotEmpty(collectionRevoke) && collectionRevoke.size() > 0) {
            return IResponse.fail("撤销收款业务审核中，无法申请!");
        }
        //通过feign调用basic的校验
        IResponse<String> result = loanChangeFegin.repaymentChangeValid(contractNo);
        if (CommonConstants.FAIL.equals(result.getCode()) || EmptyUtils.isEmpty(result.getData())) {
            return IResponse.fail("获取校验请求连接断开，请稍后再试！");
        } else {
            if (!Boolean.TRUE.toString().equals(result.getData())) {
                return IResponse.fail(result.getData());
            } else {
                return IResponse.success(true);
            }
        }
    }

    /**
     * 费用豁免有无检验
     */
    private IResponse hasCostExemptCheck(String contractNo) {

        Map<String, String> headers = new HashMap<>();
        headers.put(AfsEnumUtil.key(ContractFeginParamEnum.BASIC_CLIENT_ID), contractFeginConfig.getBasicClientId());
        headers.put(AfsEnumUtil.key(ContractFeginParamEnum.BASIC_CLIENT_SECRET), contractFeginConfig.getBasicClientSecret());
        BasicExpenseRecordDetailDto dto = new BasicExpenseRecordDetailDto();
        dto.setContractNo(contractNo);
        IResponse canCostExempt = basicMainInfoFeign.getCanCostExempt(dto, headers);
        boolean result = (boolean) canCostExempt.getData();
        if (!result) {
            return IResponse.fail("该合同没有费用，无需做费用豁免");
        }
        return IResponse.success(true);
    }

    /**
     * 合同取消校验
     */
    private IResponse cancelContractValid(String contractNo, Boolean isSp) {
        //通过fegin调用basic的校验
        IResponse<String> result = basicMainInfoFeign.cancelContractValid(contractNo, isSp);
        if (!Boolean.TRUE.toString().equals(result.getData())) {
            return IResponse.fail(result.getData());
        }
        return IResponse.success(true);
    }

    /**
     * 收款撤销校验
     *
     * @return
     */
    private IResponse collectionRevokeValid(String contractNo) {
        List<ManageApplyRecord> collectCancel = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getContractNo, contractNo)
                .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.collectionRevoke)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW));
        if (EmptyUtils.isNotEmpty(collectCancel)) {
            return IResponse.fail("该合同有正在撤销数据，不可再次发起！");
        }
        /**  豁免类（审核中） **/
        List<ManageApplyRecord> manageApplyRecords = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getContractNo, contractNo)
                .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.exemptTypes)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW));
        if (manageApplyRecords.size() > 0) {
            return IResponse.fail("豁免业务审核中，不可发起撤销！");
        }
        List<ManageApplyRecord> overpayment = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getContractNo, contractNo)
                .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.overpayment)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW));
        if (EmptyUtils.isNotEmpty(overpayment)) {
            return IResponse.fail("溢缴款在审批中，无法审批！");
        }
        return IResponse.success(true);
    }

    /**
     * 收款撤销成功处理校验
     *
     * @return
     */
    private IResponse revokeHandleValid(String contractNo) {
        List<ManageRevokeHandle> list = manageRevokeHandleService.list(Wrappers.<ManageRevokeHandle>query().lambda()
                .eq(ManageRevokeHandle::getContractNo, contractNo).eq(ManageRevokeHandle::getProcessStatus, ProcessStatusEnum.underReview)
        );
        if (EmptyUtils.isNotEmpty(list)) {
            return IResponse.fail("该合同有正在撤销数据，不可再次发起！");
        }
        return IResponse.success(true);
    }

    /**
     * 根据合同号判断提前还款是否存在
     *
     * @param contractNo
     * @return
     */
    private IResponse getEarlyRepay(String contractNo) {

        //根据合同号查询提前还款中的单子
        List<ManagePrepaymentApply> managePrepaymentApplies = managePrepaymentApplyService.list(Wrappers.<ManagePrepaymentApply>query().lambda()
                .eq(ManagePrepaymentApply::getContractNo, contractNo)
                .in(ManagePrepaymentApply::getApplyStatus, Arrays.asList(CaseStatusEnum.NOT_SUBMIT, CaseStatusEnum.UNDER_REVIEW, CaseStatusEnum.APPROVED))
        );
        if (managePrepaymentApplies.size() > 0) {
            return IResponse.fail("该合同正在流程审核中，无法再次发起！");
        }
        return IResponse.success(true);
    }

    /**
     * 根据合同号判断是否可以发起月供对公收款
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    private boolean canStartCorporateForRent(String contractNo) {

        /**  除合同关闭和合同取消外没有其他进入详情校验 by ZC.GUO  **/
        return false;
    }

    /**
     * 根据合同号判断是否可以发起提前还款对公收款
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    private boolean canStartCorporateForPrepayment(String contractNo) {

        /**  除合同关闭和合同取消外没有其他进入详情校验 by ZC.GUO  **/
        return false;
    }

    /**
     * 罚息豁免校验
     */
    private IResponse penaltyExemptValid(String contractNo) {
        //通过fegin调用basic的校验
        IResponse<String> result = basicMainInfoFeign.penaltyExemptValid(contractNo);
        if (!Boolean.TRUE.toString().equals(result.getData())) {
            return IResponse.fail(result.getData());
        }
        return IResponse.success(true);
    }

    /**
     * 除保险业务，其他业务均需要校验合同是否关闭、是否取消
     */
    private IResponse checkCloseOrCancel(String contractNo,DataSourceEnum dataSource){

        //cms校验
        if (EmptyUtils.isNotEmpty(dataSource)&&dataSource.equals(DataSourceEnum.cms)) {
            //合同取消校验
            CmsCheckRequestDTO cmsCheckRequestDTO = new CmsCheckRequestDTO();
            cmsCheckRequestDTO.setContractNo(contractNo);
            cmsCheckRequestDTO.setStartIndex(0);
            cmsCheckRequestDTO.setStepLength(10);
            CmsResponse<CmsQueryContractResponseDTO> cmsBaseResponseDTO = cmsCheckFeign.cancelOrClose(cmsCheckRequestDTO);

            if (AfsEnumUtil.key(SuccessResponseEnum.FAIL).equals(cmsBaseResponseDTO.getSuccess()) && !AfsEnumUtil.key(CodeResponseEnum.M10051).equals(cmsBaseResponseDTO.getCode())) {
                throw new AfsBaseException("获取cms系统合同状态失败，请重试！");
            }
            List<CmsContractInfo> contracts = cmsBaseResponseDTO.getData().getContracts();
            CmsContractInfo cmsContractInfo = contracts.get(0);
            //合同取消校验
            if (cmsContractInfo.getContractStatus().equals(100)) {
                return IResponse.fail("合同已取消，无法申请贷后业务！");
                //合同关闭校验
            }
//            else if (cmsContractInfo.getContractStatus().equals("contractClose")) {
//                return IResponse.fail("合同已结清，无法申请贷后业务！");
//            }
        } else {
            //多品合同校验
            //合同取消校验
            IResponse<String> status = basicInfoFeign.cancelOrClose(contractNo);
            if (CommonConstants.FAIL.equals(status.getCode()) || EmptyUtils.isEmpty(status.getData())) {
                return IResponse.fail("获取校验请求连接断开，请稍后再试！");
            } else {
                //合同取消校验
                if (status.getData().equals("contractCancel")) {
                    return IResponse.fail("合同已取消，无法申请贷后业务！");
                } else if (status.getData().equals("contractClose")) {
                //合同关闭校验
                    return IResponse.fail("合同已结清，无法申请贷后业务！");
                }
            }
        }
        return IResponse.success(true);
    }


}
